#include <interfacelib/frame/Frame.h>
#include <interfacelib/directx/initd3d.h>
#include <interfacelib/Window/Button.h>
#include <interfacelib/frame/handlemanager.h>
#include <interfacelib/directx/synchronized_dx.h>
#include <netlib/net/socket.h>

using namespace interfacelib::Frame;

Frame::Frame() : m_previousFrame( NULL ), m_modalDialog( NULL ), m_menu( NULL ),m_processIdleMessage ( false )
{
	ZeroMemory( m_funcList, sizeof( m_funcList ) );

	m_panel.setVisible( true );
	m_panel.setWindowPos( 0, 0, interfacelib::DirectX::InitD3D::getInstance()->getWidth(), interfacelib::DirectX::InitD3D::getInstance()->getHeight() );
}

Frame::~Frame()
{
	releaseModalDialog();
	release();
}

void Frame::activate()
{
//	m_panel.setWindowPos( 0, 0, interfacelib::DirectX::InitD3D::getInstance()->getWidth(), interfacelib::DirectX::InitD3D::getInstance()->getHeight() );
//	m_panel.setMovable( false );

	releaseModalDialog();
	
	m_panel.initialize();
	m_menu = NULL;
}

void Frame::release()
{
}

void Frame::preTranslateMessage( MSG *msg )
{
	if ( m_modalDialog && msg->message == WM_KEYDOWN ) 
	{
		bool returnCode = false;
		if ( msg->wParam == VK_ESCAPE ) returnCode = m_modalDialog->onESCKeyDown();
		if ( msg->wParam == VK_RETURN ) returnCode = m_modalDialog->onEnterKeyDown();
		if ( returnCode == true ) return;
	}
	if ( preTranslateNetworkMessage( msg->message, msg->wParam, msg->lParam ) == true ) return;
	if ( callEventProcedure( msg ) == true ) return;
	if ( notifySystemMessage( msg ) == true ) return;

	interfacelib::Window::Window *menu = m_menu;

	m_panel.preTranslateMessage( msg );

	if ( menu == m_menu && ( msg->message == WM_LBUTTONDOWN ||  msg->message == WM_RBUTTONDOWN ) )
		setMenu( 0, 0, NULL );
}

bool Frame::notifySystemMessage( MSG *msg )
{
	if ( !m_modalDialog ) return ( false );
	switch ( msg->message )
	{
	case WM_MODALDIALOG_CLOSE :
		{
			closeModalDialog( msg );
		}
		return ( true );
	}
//	if ( ( msg->message == WM_BUTTON_NOTIFY ) && ( msg->lParam == interfacelib::Window::Button::BUTTON_STATE_CLICK ) ) m_modalDialog->buttonNotify( ( interfacelib::Window::Window * )msg->wParam);
//	else

	bool eventProcess = true;
	if ( m_modalDialog->isPointInWindow( msg->pt.x, msg->pt.y ) == false )
	{
		if ( msg->message == WM_MOUSEMOVE || msg->message == WM_LBUTTONDOWN ) // msg->message == WM_LBUTTONUP || 
			eventProcess = false;
	}	
	if ( eventProcess == true ) m_modalDialog->preTranslateMessage( msg );


	return ( true );
}
	
bool Frame::callEventProcedure( MSG *msg )
{
	switch ( msg->message )
	{
	case WM_BUTTON_NOTIFY :
		{
			mouseEvent( msg->wParam, msg->lParam );
		}
		return ( true );
	case WM_EDITBOX_NOTIFY :
		{
			editEvent( msg->wParam, msg->lParam );
		}
		return ( true );
	case WM_USER_NOTIFY :
		{
			onUserNotify( msg->wParam, msg->lParam );
		}
		return ( true );
	case WM_MEMU_SELECT :
		{
			onMenuSelect( msg->wParam, msg->lParam );
		}
		return ( true );
	}
	return ( false );
}

bool Frame::preTranslateNetworkMessage( UINT messageID, WPARAM wparam, LPARAM lparam )
{
	switch ( messageID )
	{
	case WM_SOCKET_CONNECT :
		{
			onSocketConnect( wparam, ( netlib::net::Socket * )lparam );
		}
		return ( true );
	case WM_SOCKET_CONNECTED :
		{
			onSocketConnected( wparam, ( netlib::net::Socket * )lparam );
		}
		return ( true );
	case WM_SOCKET_CLOSE :
		{
			netlib::packet::MessageQueue::getInstance()->remove( lparam );
			onSocketClose( wparam, ( netlib::net::Socket * )lparam );
		}
		return ( true );
	case WM_SOCKET_RECEIVE :
		{
			netlib::net::Socket *socket = ( netlib::net::Socket * )lparam;
			netlib::packet::Packet *packet = ( netlib::packet::Packet *)wparam;
//			netlib::net::Synchronized_Packet sync( socket );
			onSocketReceive( packet , socket );

			socket->releasePacket( packet );
		}
		return ( true );
	}

	return ( false );
}

bool Frame::buttonClickEvent(  interfacelib::Window::Window *window )
{
	UserFunction function = getUserFunction( ( void *) window );
	if ( function )
	{
		( this->*function )();
		return ( true );
	} 
	interfacelib::Window::Panel *parentPanel = window->getParentPanel();
	if ( parentPanel )
		parentPanel->buttonNotify( window );

	return ( false );

}

bool Frame::mouseEvent(  WPARAM wparam, LPARAM lparam  )
{
	if ( lparam == interfacelib::Window::Button::BUTTON_STATE_CLICK )
	{
		buttonClickEvent( ( interfacelib::Window::Window * ) wparam );;
		return ( true );
	}
	return ( false );
}

bool Frame::editEvent(  WPARAM wparam, LPARAM lparam  )
{
	return ( false );
}

bool Frame::draw()
{
#ifdef CHECK_FREAME_RATE
	static int frameCount = 0;
	static int currentFrameRate = 0;
	frameCount++;
	static DWORD previousTime = GetTickCount();
	DWORD currentTickCount = GetTickCount();
	if ( previousTime + 1000 < currentTickCount )
	{
		currentFrameRate = frameCount;
		previousTime = currentTickCount;
		frameCount = 0;
	}
#endif

	{
		interfacelib::DirectX::Synchronized_Sprite sync;
		m_panel.draw();

#ifdef CHECK_FREAME_RATE
		char str[512];
	
		wsprintf( str, "%d Frm/Sec", currentFrameRate );
		RECT rect = { 0, 0, 150, 15 };
		drawText( &rect, str );
#endif	
	}

	return ( true );
}

bool Frame::updateFrame()
{
	netlib::packet::MessageQueue::MessageInfo info;
	if ( m_processIdleMessage == true )
	{
		while ( netlib::packet::MessageQueue::getInstance()->popIdle( &info ) == true )
		{
			preTranslateNetworkMessage( info.messageID, info.wparam, info.lparam );
		}
	}

	if ( netlib::packet::MessageQueue::getInstance()->pop( &info ) == true )
	{
		preTranslateNetworkMessage( info.messageID, info.wparam, info.lparam );
	}
	return ( true );
}

void Frame::onSocketConnect( int param, netlib::net::Socket *socket )
{
#ifdef _DEBUG
	if ( param != 0 )
	{
		char buffer[ 128 ];
		sprintf( buffer, "Connect Error Code is %10d", param );
		MessageBox( NULL, buffer , "Error" , MB_OK );
	}
#endif
}


void Frame::onSocketReceive(  netlib::packet::Packet *packet, netlib::net::Socket *socket  )
{
	if ( !packet ) return;

	switch ( packet->ID() )
	{
	case protocol::network::EncryptKey :
		socket->setEncryptKey( packet );
		return;
	}

	MessageProcedureFunction function = getFunction( packet->ID() );
	if ( function )
	{
		( this->*function )( packet , socket );
	}

}

void Frame::setModalDialog( interfacelib::Window::Panel *panel , bool isDelete )
{
	if ( m_panel.add( panel ) == false ) return;

	panel->setSaveModalDialog( m_modalDialog , m_isDeleteSaveModalDialog );

	m_modalDialog = panel;
	m_isDeleteSaveModalDialog = isDelete;
	m_panel.setTopWindow( panel );
}

void Frame::closeModalDialog( MSG *msg )
{
	interfacelib::Window::Panel *panel = ( interfacelib::Window::Panel * )msg->lParam ;
	for ( ;; )
	{
		interfacelib::Window::Panel *currentModalDialog = m_modalDialog;
		bool isDelete = false;
		m_modalDialog = currentModalDialog->getSaveModalDialog( isDelete );
		m_panel.remove( currentModalDialog , m_isDeleteSaveModalDialog );
		m_isDeleteSaveModalDialog = isDelete;

		if ( ( !m_modalDialog ) || ( panel == currentModalDialog ) ) break;
	}
	MSG mouseEvent;
	memcpy( &mouseEvent, msg, sizeof( MSG ) );
	mouseEvent.message = WM_MOUSEMOVE;

	if ( m_modalDialog )
	{
		m_panel.setTopWindow( m_modalDialog );
		m_modalDialog->getWindowPos( &mouseEvent.pt );
	}

	m_panel.preTranslateMessage( &mouseEvent );

}

void Frame::releaseModalDialog()
{
	for ( ;; )
	{
		if ( !m_modalDialog ) return;
		interfacelib::Window::Panel *currentModalDialog = m_modalDialog;
		
		bool isDelete = false;
		m_modalDialog = currentModalDialog->getSaveModalDialog( isDelete );
		m_panel.remove( currentModalDialog , m_isDeleteSaveModalDialog );
		m_isDeleteSaveModalDialog = isDelete;
	}
}

void Frame::setMenu( int x, int y, interfacelib::Window::Window *menu )
{
	if ( m_menu ) m_menu->setVisible( false );
	m_menu = menu;
	if ( m_menu )
	{
		m_menu->setWindowPos( x, y );
		( ( interfacelib::Window::Window * )m_menu )->setTopWindow();
	}
}